//
// Copyright (c) 2014, 保留所有权利。
//
// MergeHandler.java
//
// 作    者：王红燕
// 当前版本：1.0
// 2014 上午10:19:55
//
// 
//
package com.common.api.handler;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.List;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.wang.hongyan.common.lock.LockContext;

import com.vanke.agent.ADataSource;
import com.vanke.agent.C;
import com.vanke.agent.bean.FollowRecord;
import com.vanke.agent.common.CstUtil;
import com.vanke.agent.common.FollowRecordUtil;
import com.vanke.agent.common.log.LoggerUtil;
import com.vanke.agent.tools.merge.Merge;

/**
 *
 */
public class MergeHandler extends ApiHandler {
	static Logger log = LoggerUtil.getLoggerByName("api_invoke");

	/*
	 * 请求参数：
	 * {
	 * "header":{"cmd": "merge"}, // 调用命令，供外层调度用
	 * "to": 456, // 本次合并要保留的客户的ID
	 * "from": 123, // 本次合并被合并掉的（丢弃）客户的ID
	 * "fix": 0 // 是否自动修正保留有推荐关系的客户，0表示不修正
	 * }
	 * 
	 * 响应参数：
	 * {
	 * "errcode": 0, // 错误码，0为成功
	 * "errmsg": "", // 错误描述
	 * "retain": 123 // 本次合并实际保留的客户ID
	 * }
	 */
	@Override
	public JSONObject handle(JSONObject json) {
		log.info("handle merge: " + json);

		String fieldFrom = "from", fieldTo = "to";
		if (!json.containsKey(fieldFrom)) {
			return genErr(1001, "缺少必须参数[" + fieldFrom + "]");
		}
		if (!json.containsKey(fieldTo)) {
			return genErr(1001, "缺少必须参数[" + fieldTo + "]");
		}
		long from = 0;
		long to = 0;
		try {
			from = json.getLong(fieldFrom);
		} catch (Exception e) {
			log.error(e);
			if (e.getMessage() != null
					&& e.getMessage().contains("is not a number")) {
				return genErr(1002, fieldFrom);
			}
			return genErr(1005, "系统处理失败");
		}
		try {
			to = json.getLong(fieldTo);
		} catch (Exception e) {
			log.error(e);
			if (e.getMessage() != null
					&& e.getMessage().contains("is not a number")) {
				return genErr(1002, fieldTo);
			}
			return genErr(1005, "系统处理失败");
		}

		log.info("[MergeHandler]锁定客户[" + from + "," + to + "]");
		boolean fromLock = LockContext.tryLock(from, C.LOCK_TRY_TIMEOUT);
		boolean toLock = LockContext.tryLock(to, C.LOCK_TRY_TIMEOUT);
		if (!fromLock || !toLock) {
			if (fromLock) {
				LockContext.unlock(from);
			}
			if (toLock) {
				LockContext.unlock(to);
			}
			log.error("获取客户锁失败，无法执行合并");
			return genErr(1005, "获取客户锁失败");
		}
		log.info("[MergeHandler]成功锁定客户[" + from + "," + to + "]");
		try {
			if (json.containsKey("fix")) {
				try {
					int fix = json.getInt("fix");
					if (fix == 0) {
						return noFixMerge(from, to);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return fixMerge(from, to);
		} catch (Exception e) {
			e.printStackTrace();
			return genErr(1005, "系统处理失败");
		} finally {
			if (fromLock) {
				LockContext.unlock(from);
			}
			if (toLock) {
				LockContext.unlock(to);
			}
		}
	} //~handle

	/*
	 * 合并主档
	 */
	public JSONObject noFixMerge(long from, long to) {
		Connection con = ADataSource.getConnection(ADataSource.SCHEMA_BIZ);
		try {
			if (from == to) {
				return genErr(1004, String.format("相同客户信息合并[%s,%s]", from, to));
			}

			// 只有在from有推荐，to没有的情况下才取from；其余均取to
			log.info("实际执行合并[" + from + "->" + to + "]");

			// 被合并掉的主档的跟进记录列表（不含预约）
			List<FollowRecord> frList = FollowRecordUtil.loadFollowRecord(con,
					from, "", log);

			Merge merge = new Merge();
			// 是否合并成功
			boolean merged = merge.mergeCst(from, to);

			if (!merged) {
				return genErr(1005, "系统处理失败");
			}
			long retainGuid = to;
			long dropedGuid = from;

			log.info("合并成功!");
			log.info("发送客户资料合并通知");
			CstUtil.sendMergeNotice(retainGuid, dropedGuid, null);
			log.info("重推跟进通知");
			// 如果合并成功，则将通知下发
			FollowRecordUtil.resendFollowRecords(frList, to);
			JSONObject result = getDefResult();
			result.put("retain", to);
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return genErr(1005, "系统处理失败");
		} finally {
			ADataSource.close(con);
		}
	} //~noFixMerge

	/*
	 * 合并主档
	 */
	public JSONObject fixMerge(long from, long to) {
		Connection con = ADataSource.getConnection(ADataSource.SCHEMA_BIZ);
		try {
			if (from == to) {
				return genErr(1004, String.format("相同客户信息合并[%s,%s]", from, to));
			}

			Merge merge = new Merge();
			// 默认取都无推荐关系
			boolean toHas = hasRecommend(con, to);
			boolean fromHas = hasRecommend(con, from);
			log.info(String.format("是否有推荐关系检查[%s:%s,%s:%s]", // 
					from, fromHas ? "有" : "无", 	//
					to, toHas ? "有" : "无"		//
			));

			// 只有在from有推荐，to没有的情况下才取from；其余均取to
			List<FollowRecord> frList; 	// 被合并掉的主档的跟进记录列表（不含预约）
			long retainGuid;			// 合并后保留的GUID
			long dropedGuid;			// 合并后丢丢弃的GUID
			boolean merged = false;		// 是否合并成功
			if (fromHas && !toHas) {
				log.info("实际执行合并[" + to + "->" + from + "]");
				frList = FollowRecordUtil.loadFollowRecord(con, to, "", log);
				merged = merge.mergeCst(to, from);
				retainGuid = from;
				dropedGuid = to;
			} else {
				log.info("实际执行合并[" + from + "->" + to + "]");
				frList = FollowRecordUtil.loadFollowRecord(con, from, "", log);
				merged = merge.mergeCst(from, to);
				retainGuid = to;
				dropedGuid = from;
			}
			if (!merged) {
				return genErr(1005, "系统处理失败");
			}

			log.info("合并成功!");
			log.info("发送客户资料合并通知");
			CstUtil.sendMergeNotice(retainGuid, dropedGuid, null);
			log.info("重推跟进通知");
			// 如果合并成功，则将通知下发
			FollowRecordUtil.resendFollowRecords(frList, retainGuid);
			JSONObject result = getDefResult();
			result.put("retain", retainGuid);
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return genErr(1005, "系统处理失败");
		} finally {
			ADataSource.close(con);
		}
	} //~fixMerge(long from, long to)

	/*
	 * 检查是否有推荐关系
	 */
	protected boolean hasRecommend(Connection con, long guid) {
		//	prm_Agent_Cst_Recommed_
		String table = CstUtil.calcCstSplitTable("prm_Agent_Cst_Recommed_",
				guid);
		Statement stmt = null;
		ResultSet rs = null;
		try {
			String sql = "select cstguid from " + table + " where cstguid="
					+ guid;
			stmt = con.createStatement();
			rs = stmt.executeQuery(sql);
			return rs.next();
		} catch (Exception e) {
			e.printStackTrace();
			log.error("检推荐关系异常：" + e);
			return false;
		} finally {
			ADataSource.close(rs, stmt, null);
		}
	} //~hasRecommend(Connection con, long guid)

} ///~MergeHandler
